/**
 * 集成测试运行器
 * Integration Test Runner
 */

const path = require('path');
const fs = require('fs').promises;
const { spawn } = require('child_process');

// 颜色定义
const colors = {
  reset: '\x1b[0m',
  red: '\x1b[31m',
  green: '\x1b[32m',
  yellow: '\x1b[33m',
  blue: '\x1b[34m',
  purple: '\x1b[35m',
  cyan: '\x1b[36m'
};

function printMessage(color, message) {
  console.log(`${color}${message}${colors.reset}`);
}

/**
 * 测试套件配置
 */
const testSuites = [
  {
    name: '端到端集成测试',
    description: '完整的API和功能测试',
    script: 'e2e-test-suite.js',
    timeout: 300000, // 5分钟
    critical: true
  },
  {
    name: '用户工作流程测试',
    description: '模拟真实用户使用场景',
    script: 'user-workflow.test.js',
    timeout: 180000, // 3分钟
    critical: true
  },
  {
    name: '负载测试',
    description: '系统性能和并发能力测试',
    script: 'load-test.js',
    timeout: 600000, // 10分钟
    critical: false
  }
];

/**
 * 测试运行器类
 */
class IntegrationTestRunner {
  constructor() {
    this.results = [];
    this.startTime = null;
    this.endTime = null;
  }

  /**
   * 运行单个测试套件
   */
  async runTestSuite(suite) {
    printMessage(colors.cyan, `\n运行测试套件: ${suite.name}`);
    printMessage(colors.blue, `描述: ${suite.description}`);
    printMessage(colors.blue, `脚本: ${suite.script}`);
    console.log();

    const scriptPath = path.join(__dirname, suite.script);
    const startTime = Date.now();

    return new Promise((resolve) => {
      const child = spawn('node', [scriptPath], {
        stdio: 'inherit',
        cwd: __dirname
      });

      // 设置超时
      const timeout = setTimeout(() => {
        child.kill('SIGTERM');
        resolve({
          name: suite.name,
          success: false,
          error: '测试超时',
          duration: Date.now() - startTime,
          critical: suite.critical
        });
      }, suite.timeout);

      child.on('close', (code) => {
        clearTimeout(timeout);
        const duration = Date.now() - startTime;
        
        resolve({
          name: suite.name,
          success: code === 0,
          error: code !== 0 ? `测试失败，退出码: ${code}` : null,
          duration,
          critical: suite.critical
        });
      });

      child.on('error', (error) => {
        clearTimeout(timeout);
        resolve({
          name: suite.name,
          success: false,
          error: error.message,
          duration: Date.now() - startTime,
          critical: suite.critical
        });
      });
    });
  }

  /**
   * 运行所有测试套件
   */
  async runAllTests() {
    this.startTime = Date.now();
    
    printMessage(colors.cyan, '个人云笔记集成测试运行器');
    printMessage(colors.cyan, '==============================');
    
    for (const suite of testSuites) {
      const result = await this.runTestSuite(suite);
      this.results.push(result);
      
      // 显示测试结果
      if (result.success) {
        printMessage(colors.green, `✓ ${result.name} - 通过 (${Math.round(result.duration / 1000)}秒)`);
      } else {
        const color = result.critical ? colors.red : colors.yellow;
        printMessage(color, `✗ ${result.name} - 失败: ${result.error} (${Math.round(result.duration / 1000)}秒)`);
      }
    }
    
    this.endTime = Date.now();
  }

  /**
   * 生成测试报告
   */
  async generateReport() {
    const totalTests = this.results.length;
    const passedTests = this.results.filter(r => r.success).length;
    const failedTests = totalTests - passedTests;
    const criticalFailures = this.results.filter(r => !r.success && r.critical).length;
    const totalDuration = this.endTime - this.startTime;

    const report = {
      metadata: {
        generatedAt: new Date().toISOString(),
        totalDuration: totalDuration,
        testSuites: testSuites.length
      },
      summary: {
        total: totalTests,
        passed: passedTests,
        failed: failedTests,
        criticalFailures,
        successRate: Math.round((passedTests / totalTests) * 100)
      },
      results: this.results.map(result => ({
        name: result.name,
        success: result.success,
        duration: result.duration,
        critical: result.critical,
        error: result.error
      })),
      recommendations: this.generateRecommendations()
    };

    // 保存JSON报告
    const reportsDir = path.join(__dirname, '../reports');
    await fs.mkdir(reportsDir, { recursive: true });
    
    const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
    const reportPath = path.join(reportsDir, `integration-test-report-${timestamp}.json`);
    
    await fs.writeFile(reportPath, JSON.stringify(report, null, 2));

    // 生成HTML报告
    const htmlReportPath = await this.generateHtmlReport(report, reportsDir, timestamp);

    return { jsonReport: reportPath, htmlReport: htmlReportPath, report };
  }

  /**
   * 生成HTML报告
   */
  async generateHtmlReport(report, reportsDir, timestamp) {
    const htmlContent = `
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>个人云笔记集成测试报告</title>
    <style>
        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            margin: 0;
            padding: 20px;
            background-color: #f5f5f5;
        }
        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            overflow: hidden;
        }
        .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            text-align: center;
        }
        .header h1 {
            margin: 0;
            font-size: 2.5em;
        }
        .header p {
            margin: 10px 0 0 0;
            opacity: 0.9;
        }
        .summary {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
            gap: 20px;
            padding: 30px;
            background: #f8f9fa;
        }
        .summary-card {
            background: white;
            padding: 20px;
            border-radius: 8px;
            text-align: center;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        .summary-card h3 {
            margin: 0 0 10px 0;
            color: #333;
        }
        .summary-card .value {
            font-size: 2em;
            font-weight: bold;
            margin: 10px 0;
        }
        .success { color: #28a745; }
        .danger { color: #dc3545; }
        .warning { color: #ffc107; }
        .info { color: #17a2b8; }
        .results {
            padding: 30px;
        }
        .test-result {
            display: flex;
            align-items: center;
            padding: 15px;
            margin: 10px 0;
            border-radius: 8px;
            border-left: 4px solid;
        }
        .test-result.success {
            background: #d4edda;
            border-color: #28a745;
        }
        .test-result.failure {
            background: #f8d7da;
            border-color: #dc3545;
        }
        .test-result.warning {
            background: #fff3cd;
            border-color: #ffc107;
        }
        .test-icon {
            font-size: 1.5em;
            margin-right: 15px;
        }
        .test-info {
            flex: 1;
        }
        .test-name {
            font-weight: bold;
            font-size: 1.1em;
        }
        .test-duration {
            color: #666;
            font-size: 0.9em;
        }
        .test-error {
            color: #dc3545;
            font-size: 0.9em;
            margin-top: 5px;
        }
        .recommendations {
            padding: 30px;
            background: #f8f9fa;
        }
        .recommendations h2 {
            color: #333;
            margin-bottom: 20px;
        }
        .recommendation {
            background: white;
            padding: 15px;
            margin: 10px 0;
            border-radius: 8px;
            border-left: 4px solid #17a2b8;
        }
        .footer {
            text-align: center;
            padding: 20px;
            color: #666;
            font-size: 0.9em;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>个人云笔记集成测试报告</h1>
            <p>生成时间: ${new Date(report.metadata.generatedAt).toLocaleString()}</p>
        </div>
        
        <div class="summary">
            <div class="summary-card">
                <h3>总测试数</h3>
                <div class="value info">${report.summary.total}</div>
            </div>
            <div class="summary-card">
                <h3>通过测试</h3>
                <div class="value success">${report.summary.passed}</div>
            </div>
            <div class="summary-card">
                <h3>失败测试</h3>
                <div class="value danger">${report.summary.failed}</div>
            </div>
            <div class="summary-card">
                <h3>成功率</h3>
                <div class="value ${report.summary.successRate >= 80 ? 'success' : 'danger'}">${report.summary.successRate}%</div>
            </div>
            <div class="summary-card">
                <h3>总耗时</h3>
                <div class="value info">${Math.round(report.metadata.totalDuration / 1000)}秒</div>
            </div>
            <div class="summary-card">
                <h3>关键失败</h3>
                <div class="value ${report.summary.criticalFailures > 0 ? 'danger' : 'success'}">${report.summary.criticalFailures}</div>
            </div>
        </div>
        
        <div class="results">
            <h2>测试结果详情</h2>
            ${report.results.map(result => `
                <div class="test-result ${result.success ? 'success' : (result.critical ? 'failure' : 'warning')}">
                    <div class="test-icon">${result.success ? '✅' : '❌'}</div>
                    <div class="test-info">
                        <div class="test-name">${result.name}</div>
                        <div class="test-duration">耗时: ${Math.round(result.duration / 1000)}秒 ${result.critical ? '(关键测试)' : ''}</div>
                        ${result.error ? `<div class="test-error">错误: ${result.error}</div>` : ''}
                    </div>
                </div>
            `).join('')}
        </div>
        
        ${report.recommendations.length > 0 ? `
        <div class="recommendations">
            <h2>优化建议</h2>
            ${report.recommendations.map(rec => `
                <div class="recommendation">
                    <strong>${rec.title}</strong><br>
                    ${rec.description}
                </div>
            `).join('')}
        </div>
        ` : ''}
        
        <div class="footer">
            <p>个人云笔记系统 - 集成测试报告</p>
        </div>
    </div>
</body>
</html>
    `;

    const htmlReportPath = path.join(reportsDir, `integration-test-report-${timestamp}.html`);
    await fs.writeFile(htmlReportPath, htmlContent);
    
    return htmlReportPath;
  }

  /**
   * 生成优化建议
   */
  generateRecommendations() {
    const recommendations = [];
    const failedTests = this.results.filter(r => !r.success);
    const criticalFailures = failedTests.filter(r => r.critical);

    if (criticalFailures.length > 0) {
      recommendations.push({
        title: '关键测试失败',
        description: '有关键测试失败，这可能影响系统的核心功能。建议立即检查和修复相关问题。',
        priority: 'HIGH'
      });
    }

    if (failedTests.length > 0 && failedTests.length <= 2) {
      recommendations.push({
        title: '部分测试失败',
        description: '少数测试失败，建议检查失败原因并进行修复，以确保系统稳定性。',
        priority: 'MEDIUM'
      });
    }

    if (failedTests.length > 2) {
      recommendations.push({
        title: '多个测试失败',
        description: '多个测试失败表明系统可能存在较严重的问题，建议进行全面的系统检查。',
        priority: 'HIGH'
      });
    }

    const totalDuration = this.endTime - this.startTime;
    if (totalDuration > 600000) { // 10分钟
      recommendations.push({
        title: '测试执行时间过长',
        description: '测试执行时间超过10分钟，建议优化测试脚本或检查系统性能。',
        priority: 'MEDIUM'
      });
    }

    if (this.results.every(r => r.success)) {
      recommendations.push({
        title: '所有测试通过',
        description: '恭喜！所有集成测试都通过了。建议定期运行测试以确保系统持续稳定。',
        priority: 'INFO'
      });
    }

    return recommendations;
  }

  /**
   * 显示测试总结
   */
  displaySummary() {
    const totalTests = this.results.length;
    const passedTests = this.results.filter(r => r.success).length;
    const failedTests = totalTests - passedTests;
    const criticalFailures = this.results.filter(r => !r.success && r.critical).length;
    const successRate = Math.round((passedTests / totalTests) * 100);
    const totalDuration = Math.round((this.endTime - this.startTime) / 1000);

    console.log();
    printMessage(colors.cyan, '测试总结');
    printMessage(colors.cyan, '========');
    console.log();

    printMessage(colors.blue, `总测试数: ${totalTests}`);
    printMessage(colors.green, `通过测试: ${passedTests}`);
    printMessage(colors.red, `失败测试: ${failedTests}`);
    printMessage(colors.purple, `关键失败: ${criticalFailures}`);
    printMessage(colors.blue, `成功率: ${successRate}%`);
    printMessage(colors.blue, `总耗时: ${totalDuration}秒`);

    console.log();

    // 整体评估
    if (criticalFailures > 0) {
      printMessage(colors.red, '❌ 集成测试失败：存在关键功能问题');
      printMessage(colors.red, '建议立即检查和修复失败的关键测试');
    } else if (failedTests > 0) {
      printMessage(colors.yellow, '⚠️  集成测试部分失败：存在非关键问题');
      printMessage(colors.yellow, '建议检查和修复失败的测试，但不影响核心功能');
    } else {
      printMessage(colors.green, '🎉 所有集成测试通过！');
      printMessage(colors.green, '系统功能完整，可以正常使用');
    }

    return criticalFailures === 0;
  }
}

/**
 * 显示帮助信息
 */
function showHelp() {
  console.log('个人云笔记集成测试运行器');
  console.log();
  console.log('用法: node test-runner.js [选项]');
  console.log();
  console.log('选项:');
  console.log('  --help, -h        显示帮助信息');
  console.log('  --suite NAME      运行指定的测试套件');
  console.log('  --list            列出所有可用的测试套件');
  console.log('  --report-only     仅生成报告（基于现有结果）');
  console.log();
  console.log('可用的测试套件:');
  testSuites.forEach(suite => {
    console.log(`  ${suite.name}: ${suite.description}`);
  });
  console.log();
}

/**
 * 主函数
 */
async function main() {
  const args = process.argv.slice(2);

  // 处理命令行参数
  if (args.includes('--help') || args.includes('-h')) {
    showHelp();
    return;
  }

  if (args.includes('--list')) {
    console.log('可用的测试套件:');
    testSuites.forEach((suite, index) => {
      console.log(`${index + 1}. ${suite.name}`);
      console.log(`   描述: ${suite.description}`);
      console.log(`   脚本: ${suite.script}`);
      console.log(`   关键: ${suite.critical ? '是' : '否'}`);
      console.log();
    });
    return;
  }

  const suiteIndex = args.indexOf('--suite');
  if (suiteIndex !== -1 && args[suiteIndex + 1]) {
    const suiteName = args[suiteIndex + 1];
    const suite = testSuites.find(s => s.name.includes(suiteName) || s.script.includes(suiteName));
    
    if (!suite) {
      printMessage(colors.red, `未找到测试套件: ${suiteName}`);
      return;
    }

    const runner = new IntegrationTestRunner();
    const result = await runner.runTestSuite(suite);
    runner.results.push(result);
    runner.startTime = Date.now() - result.duration;
    runner.endTime = Date.now();
    
    const { jsonReport, htmlReport } = await runner.generateReport();
    runner.displaySummary();
    
    printMessage(colors.blue, `\n报告已生成:`);
    printMessage(colors.blue, `JSON: ${jsonReport}`);
    printMessage(colors.blue, `HTML: ${htmlReport}`);
    
    process.exit(result.success ? 0 : 1);
    return;
  }

  // 运行所有测试
  const runner = new IntegrationTestRunner();
  
  try {
    await runner.runAllTests();
    
    const { jsonReport, htmlReport } = await runner.generateReport();
    const success = runner.displaySummary();
    
    printMessage(colors.blue, `\n报告已生成:`);
    printMessage(colors.blue, `JSON: ${jsonReport}`);
    printMessage(colors.blue, `HTML: ${htmlReport}`);
    
    process.exit(success ? 0 : 1);
    
  } catch (error) {
    printMessage(colors.red, `测试运行失败: ${error.message}`);
    process.exit(1);
  }
}

// 错误处理
process.on('unhandledRejection', (error) => {
  printMessage(colors.red, `未处理的错误: ${error.message}`);
  process.exit(1);
});

// 运行主函数
if (require.main === module) {
  main().catch((error) => {
    printMessage(colors.red, `测试运行器启动失败: ${error.message}`);
    process.exit(1);
  });
}

module.exports = {
  IntegrationTestRunner,
  testSuites
};